﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using log4net;
using log4net.Appender;
using log4net.Config;

namespace LogToFile
{
    public class LogBase
    {
        protected static ILog sycLog;

        protected static ILog interactiveOperationLog;

        protected static ILog abnormalLog;

        protected static ILog mesLog;

        protected static ILog plcLog;

        public const int OF_READWRITE = 2;

        public const int OF_SHARE_DENY_NONE = 64;

        public static readonly IntPtr HFILE_ERROR;

        static LogBase()
        {
            HFILE_ERROR = new IntPtr(-1);
            try
            {
                XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.BaseDirectory + "./PlatformLog4Net.Config"));
                sycLog = LogManager.GetLogger("SYCLog");
                interactiveOperationLog = LogManager.GetLogger("InteractiveOperationLog");
                abnormalLog = LogManager.GetLogger("AbnormalLog");
                mesLog = LogManager.GetLogger("MESLog");
                plcLog = LogManager.GetLogger("PLCLog");
                ClearLog();
            }
            catch (Exception)
            {
            }
        }

        public static List<string> GetLogPath()
        {
            // 获取 Log4Net 配置中的所有 appender
            IAppender[] appenders = LogManager.GetRepository().GetAppenders();
            // 创建一个字符串列表用于存储日志文件路径的基本路径
            List<string> list = new List<string>();
            IAppender[] array = appenders;
            // 遍历所有的 appender
            foreach (IAppender obj in array)
            {
                string item = string.Empty;
                // 检查当前 appender 是否是 RollingFileAppender 类型
                RollingFileAppender val = (RollingFileAppender)(object)((obj is RollingFileAppender) ? obj : null);
                // 获取当前的年月，格式为 yyyyMM
                string value = DateTime.Now.ToString("yyyyMM");
                // 检查日志文件路径中是否包含年月字符串
                if (((FileAppender)val).File.IndexOf(value) != -1)
                {
                    // 提取出年月之前的基本路径部分
                    item = ((FileAppender)val).File.Substring(0, ((FileAppender)val).File.IndexOf(value));
                }
                // 如果基本路径列表中不存在这个路径，则添加进去
                if (!list.Contains(item))
                {
                    list.Add(item);
                }
            }

            return list;
        }

        public static void ClearLog()
        {
            Task.Factory.StartNew(Init);
        }

        private static void Init()
        {
            List<string> logPath = GetLogPath();
            string s = ConfigurationManager.AppSettings["LogSaveDay"];
            int result = 0;
            if (!int.TryParse(s, out result))
            {
                result = 180;
            }

            try
            {
                foreach (string item in logPath)
                {
                    if (!string.IsNullOrEmpty(item))
                    {
                        DeleteFile(item, result);
                    }
                }
            }
            catch (Exception ex)
            {
                sycLog.Error((object)"清除日志异常：", ex);
            }
        }

        private static void DeleteFile(string fileDirect, int saveDay)
        {
            try
            {
                _ = DateTime.Now;
                if (!Directory.Exists(fileDirect))
                {
                    return;
                }

                string[] files = Directory.GetFiles(fileDirect, "*.log", SearchOption.AllDirectories);
                for (int i = 0; i < files.Length; i++)
                {
                    FileInfo fileInfo = new FileInfo(files[i]);
                    if ((DateTime.Now - fileInfo.CreationTime).Days > saveDay && IsOccupy(fileInfo.FullName))
                    {
                        File.Delete(fileInfo.FullName);
                    }
                }
            }
            catch (Exception ex)
            {
                sycLog.Error((object)"删除日志异常：", ex);
            }
        }

        [DllImport("kernel32.dll")]
        public static extern IntPtr _lopen(string lpPathName, int iReadWrite);

        [DllImport("kernel32.dll")]
        public static extern bool CloseHandle(IntPtr hObject);

        private static bool IsOccupy(string file)
        {
            bool result = true;
            try
            {
                if (!File.Exists(file))
                {
                    result = false;
                }

                IntPtr intPtr = _lopen(file, 66);
                if (intPtr == HFILE_ERROR)
                {
                    sycLog.Info((object)"清除日志时，⽂件被占⽤");
                    result = false;
                }

                CloseHandle(intPtr);
            }
            catch (Exception ex)
            {
                sycLog.Error((object)"判断⽂件是否被占⽤异常：", ex);
                result = false;
            }

            return result;
        }
    }
       
}
